/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "nci_base.h"
#include "nci_transport.h"
#include "nci_api.h"
#include "stdio.h"
#include "message_queue.h"
#include "nfc_log_api.h"
#include "nfc_osi_api.h"
#include "nci_dispater.h"
#include "nfc_hex_utils.h"
#include "nci_data.h"
#include "nci_task.h"
#include "nci_core.h"

/**
 * @file nci_transport.c
 * @brief NCI传输层接口实现
*/

#define NCI_MAX_CALLBACK_SIZE 10
#define NCI_EVENT_DATA_RECV 0x100
#define NCI_EVENT_CONTROL_PACKET_RECV 0x101
#define NCI_EVENT_HAL_EVENT_RECV 0x102

/** @brief 等待传输层Event结构体 */
typedef struct {
    /** @brief 等待的Event事件 */
    tNFC_EVENT event;
    /** @brief 接收到Event后用于保存状态 */
    tNFC_STATUS status;
    /** @brief 表示是否已经接收到Event */
    bool is_received;
} tNFC_WAIT_EVENT;

static volatile bool s_nci_initialized = false;
static tMUTEX s_nci_event = MUTEX_INIT_VAL("nci_event"); // 用于NCI RSP/NTF的等待通知
static tMUTEX s_nci_lock = MUTEX_INIT_VAL("nci"); // 用于保证同时只有一个线程在发送NCI指令

static volatile tNFC_WAIT_EVENT *s_p_wait_event = NULL;
// TODO 从config中读取超时时间
static uint64_t s_nfc_open_timeout = 10 * 1000; // 10秒
static uint64_t s_core_init_timeout = 10 * 1000; // 10秒
static uint64_t s_nfc_close_timeout = 10 * 1000; // 10秒

static tPRIORITY_QUEUE s_wait_queue;
static tPRIORITY_QUEUE s_pbf_queue;
static tMESSAGE_QUEUE s_mq_nci = MQ_INIT_VAL("nci_transport");
static tNCI_STATUS write_nci_buf(tNCI_BUF *buf, tNCI_DATA_CHANNEL *channel, tTIMESTAMP timeout_time);
static tNCI_STATUS write_nci_message(tNCI_MESSAGE *msg, tNCI_DATA_CHANNEL *channel, tTIMESTAMP timeout_time);
static tNCI_STATUS request_nfc_event(tNFC_EVENT event);
static void tp_data_callback(uint16_t data_len, uint8_t* data);
static tNCI_STATUS notify_data_recv(uint8_t conn_id, uint8_t status, tNCI_BUF *buf);

/**
 * @brief 发送NCI指令，并且等待其指令的RSP，但是不获取RSP的值
 * 等同于调用send_nci_get_rsp_ntf(cmd, NULL, NULL, false, NCI_DEFAULT_WAIT_TIME);
 *
 * @param cmd 需要发送的NCI指令
 * @return NCI_STATUS_OK: 发送成功且获取到RSP
 *         NCI_STATUS_EXT_CMD_SEND_FAILED: 发送失败
 *         NCI_STATUS_EXT_WAIT_RSP_TIMEOUT: 等待RSP超时
 *         其他错误码: 其他错误
*/
tNCI_STATUS nci_tp_send_nci(tNCI_BUF *cmd) {
    return nci_tp_send_nci_get_rsp_ntf(cmd, NULL, NULL, false, NCI_DEFAULT_WAIT_TIME);
}

/**
 * @brief 发送NCI指令，并且等待其指令的RSP和NTF
 *
 * @param cmd 需要发送的NCI指令
 * @param rsp 用于保存RSP数据的指针，如果不需要保存，则置为NULL
 * @param ntf 用于保存NTF数据的指针，如果不需要保存，则置为NULL
 * @param wait_ntf 是否需要等待NTF，如果不需要，则置为false
 * @param timeout 等待超时时间
 * @return NCI_STATUS_OK: 发送成功且获取到RSP
 *         NCI_STATUS_EXT_CMD_SEND_FAILED: 发送失败
 *         NCI_STATUS_EXT_WAIT_RSP_TIMEOUT: 等待RSP超时
 *         NCI_STATUS_EXT_WAIT_NTF_TIMEOUT: 等待NTF超时
 *         其他错误码: 其他错误
*/
tNCI_STATUS nci_tp_send_nci_get_rsp_ntf(tNCI_BUF *cmd, tNCI_BUF *rsp, tNCI_BUF *ntf, bool wait_ntf, uint32_t timeout) {
    if (!cmd) {
        NFCLOG_E("cmd is null");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    tNCI_WAIT_BUF *p_ntf_wait_buf = NULL;
    uint8_t wait_buf_size = 0;
    if (wait_ntf) {
        // 需要等待NTF的场景，设置NTF等待列表
        p_ntf_wait_buf = osi_calloc(sizeof(tNCI_WAIT_BUF));
        if (!p_ntf_wait_buf) {
            NFCLOG_E("alloc ntf wait buf failed");
            return NCI_STATUS_EXT_ALLOC_FAILED;
        }
        p_ntf_wait_buf->is_received = false;
        p_ntf_wait_buf->head = cmd->head;
        p_ntf_wait_buf->head.mt = NCI_NTF;
        p_ntf_wait_buf->head.pbf = 0;
        p_ntf_wait_buf->buf = ntf;
        p_ntf_wait_buf->matched_status = NCI_STATUS_OK;
        wait_buf_size = 1;
    }
    tNCI_STATUS ret = nci_tp_send_nci_get_rsp_wait_ntf(cmd, rsp, timeout, false, p_ntf_wait_buf, wait_buf_size, wait_buf_size ? nci_tp_default_ntf_wait_cback : NULL);

    if (p_ntf_wait_buf) {
        osi_free(p_ntf_wait_buf);
    }
    return ret;
}

/**
 * @brief 默认的NTF等待回调函数实现，只要p_ntf_wait_list中有一个接收到就返回true终止其他的等待
 *
 * @param cmd 发送的NCI指令头
 * @param rsp 接收到的NCI RSP
 * @param p_ntf_wait_list NTF等待列表的指针
 * @param ntf_wait_list_size NTF等待列表的大小
 * @param p_return_status 用于输出等待到的NTF的状态
 *
 * @return 当p_ntf_wait_list中有一个NTF接收到，则返回true，否则返回false
 */
bool nci_tp_default_ntf_wait_cback(tNCI_HEAD cmd, tNCI_BUF *rsp, tNCI_WAIT_BUF *p_ntf_wait_list, uint8_t ntf_wait_list_size, tNCI_STATUS *p_return_status) {
    (void) cmd;
    (void) rsp;
    if (!p_ntf_wait_list) {
        return false;
    }
    for (uint8_t i = 0; i < ntf_wait_list_size; i++) {
        tNCI_WAIT_BUF *p_ntf_wait_buf = &p_ntf_wait_list[i];
        if (p_ntf_wait_buf->is_received) {
            if (p_return_status) {
                *p_return_status = p_ntf_wait_buf->matched_status;
                return true;
            }
        }
    }
    return false;
}

/**
 * @brief 发送NCI指令，并且等待其指令的RSP，可以自定义如何等待NTF
 *
 * @param[in] cmd 需要发送的NCI指令
 * @param[out] rsp 用于保存RSP数据的指针，如果不需要保存，则置为NULL，此指针会传递给rsp_cback函数
 * @param[in] timeout 等待超时时间
 * @param[in] ignore_rsp_status 是否忽略RSP的状态，如果为true则不会检查RSP的状态
 * @param[inout] p_ntf_wait_list 设置的NTF等待队列的指针
 * @param[in] ntf_wait_list_size NTF等待列表的大小
 * @param[in] ntf_wait_cback NTF等待回调函数，在获取到RSP后和没接收到一次NTF后都会调用此函数，此回调函数返回true后会终止等待NTF
 * @return 如果设置了NTF等待列表则返回ntf_wait_cback中返回的状态，反之返回RSP接收状态
*/
tNCI_STATUS nci_tp_send_nci_get_rsp_wait_ntf(tNCI_BUF *cmd, tNCI_BUF *rsp, uint32_t timeout, bool ignore_rsp_status,
                                            tNCI_WAIT_BUF *p_ntf_wait_list, uint8_t ntf_wait_list_size, tNCI_NTF_WAIT_CBACK ntf_wait_cback) {
    if (cmd == NULL) {
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    // 获取同步锁，保证同时只有一个线程在发送NCI指令
    // 使用这把锁的目的是防止s_nci_event在wait中被释放，导致其他线程也进入
    if (osi_mutex_lock(&s_nci_lock) != NFC_STATUS_OK) {
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }

    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    // 获取事件锁，用于等待RSP到达事件
    if (osi_mutex_lock(&s_nci_event) != NFC_STATUS_OK) {
        ret = NCI_STATUS_EXT_GET_LOCK_FAILED;
        NFCLOG_E("get nci event lock failed");
        goto unlock;
    }
    if (!s_nci_initialized) {
        ret = NCI_STATUS_EXT_NOT_INITIALIZED;
        NFCLOG_E("nci not initialized");
        goto unlock;
    }

    tNCI_WAIT_BUF rsp_wait = {};
    // 向传输层写入NCI数据
    ret = write_nci_buf(cmd, NULL, 0);

    if (ret != NCI_STATUS_OK) {
        ret = NCI_STATUS_EXT_CMD_SEND_FAILED;
        goto cleanup;
    }

    // 设置RSP等待队列
    tNCI_HEAD *head = &cmd->head;
    rsp_wait.head = *head;
    rsp_wait.head.mt = NCI_RSP;
    rsp_wait.head.pbf = 0;
    rsp_wait.buf = rsp;
    if (!pq_enqueue(&s_wait_queue, &rsp_wait, 0, 0, &rsp_wait.queue_id)) {
        ret = NCI_STATUS_EXT_FAILED;
        NFCLOG_E("set rsp wait queue failed");
        goto cleanup;
    }
    // 设置NTF等待队列
    if (p_ntf_wait_list && ntf_wait_cback) {
        for (uint8_t i = 0; i < ntf_wait_list_size; i++) {
            if (!pq_enqueue(&s_wait_queue, &p_ntf_wait_list[i], 0, 0, &p_ntf_wait_list[i].queue_id)) {
                ret = NCI_STATUS_EXT_FAILED;
                NFCLOG_E("set ntf wait queue failed, index=%d", i);
                goto cleanup;
            }
        }
    }

    // 计算RSP超时时间
    tTIMESTAMP start;
    if (osi_boot_time_ms(&start) != NFC_STATUS_OK) {
        ret = NCI_STATUS_EXT_FAILED;
        NFCLOG_E("get curr time failed");
        goto cleanup;
    }
    tTIMESTAMP timeout_time = start + timeout;

    while (!rsp_wait.is_received) {
        // 循环等待NCI RSP直到超时，防止线程被异常唤醒后不会继续等待NCI RSP
        tTIMESTAMP curr;
        if (osi_boot_time_ms(&curr) != NFC_STATUS_OK) {
            ret = NCI_STATUS_EXT_FAILED;
            NFCLOG_E("get curr time failed");
            goto cleanup;
        }
        if (curr >= timeout_time) {
            ret = NCI_STATUS_EXT_TIMEOUT;
            NFCLOG_E("wait nci rsp timeout");
            goto cleanup;
        }

        uint32_t remain_timeout = timeout_time - curr;
        NFCLOG_D("wait nci rsp: remain=%d ms", remain_timeout);
        // 等待NCI RSP
        tNFC_STATUS wait_ret = osi_mutex_wait(&s_nci_event, remain_timeout);

        if (wait_ret == NFC_STATUS_TIMEOUT) {
            ret = NCI_STATUS_EXT_WAIT_RSP_TIMEOUT;
            NFCLOG_W("nci_tp_send_nci: %02X%02X wait rsp timeout", head->hdr[0], head->hdr[1]);
            goto cleanup;
        } else if (wait_ret != NFC_STATUS_OK) {
            ret = NCI_STATUS_EXT_WAIT_FAILED;
            NFCLOG_E("wait nci rsp failed, %d", wait_ret);
            goto cleanup;
        }
    }

    if (!ignore_rsp_status) {
        ret = rsp_wait.rsp_status;
        if (ret != NCI_STATUS_OK) {
            NFCLOG_E("rsp status: %d is not success", ret);
            goto cleanup;
        }
    }

    if (!p_ntf_wait_list || ntf_wait_list_size == 0 || !ntf_wait_cback) {
        // 不需要等待NTF，直接返回
        goto cleanup;
    }
    // 检查是否已经有NTF已经到了
    if (ntf_wait_cback(cmd->head, rsp, p_ntf_wait_list, ntf_wait_list_size, &ret)) {
        NFCLOG_I("NTF arrived early, no waiting, status=%d", ret);
        goto cleanup;
    }

    // 重新计算NTF的超时时间
    if (osi_boot_time_ms(&start) != NFC_STATUS_OK) {
        ret = NCI_STATUS_EXT_FAILED;
        NFCLOG_E("get curr time failed");
        goto cleanup;
    }
    timeout_time = start + timeout;
    // 等待NCI NTF
    while (true) {
        // 检查是否已经有NTF已经到了
        if (ntf_wait_cback(cmd->head, rsp, p_ntf_wait_list, ntf_wait_list_size, &ret)) {
            NFCLOG_I("NTF arrived early, no waiting, status=%d", ret);
            goto cleanup;
        }
        // 循环等待NCI NTF直到超时，防止线程被异常唤醒后不会继续等待NCI NTF
        tTIMESTAMP curr;
        if (osi_boot_time_ms(&curr) != NFC_STATUS_OK) {
            ret = NCI_STATUS_EXT_FAILED;
            NFCLOG_E("get curr time failed");
            goto cleanup;
        }
        if (curr >= timeout_time) {
            ret = NCI_STATUS_EXT_TIMEOUT;
            NFCLOG_E("wait nci ntf timeout");
            goto cleanup;
        }

        uint32_t remain_timeout = timeout_time - curr;
        NFCLOG_D("wait nci ntf: remain=%d ms", remain_timeout);
        tNFC_STATUS wait_ret = osi_mutex_wait(&s_nci_event, remain_timeout);
        if (wait_ret == NFC_STATUS_TIMEOUT) {
            ret = NCI_STATUS_EXT_WAIT_NTF_TIMEOUT;
            NFCLOG_W("nci_tp_send_nci: %02X%02X wait ntf timeout", head->hdr[0], head->hdr[1]);
            goto cleanup;
        } else if (wait_ret != NFC_STATUS_OK) {
            ret = NCI_STATUS_EXT_WAIT_FAILED;
            NFCLOG_E("wait nci ntf failed, %d", wait_ret);
            goto cleanup;
        }
    }

cleanup:
    pq_remove(&s_wait_queue, rsp_wait.queue_id);
    if (p_ntf_wait_list) {
        // 移除等待队列
        for (uint8_t i = 0; i < ntf_wait_list_size; i++) {
            // 移除并释放等待队列中的元素
            pq_remove(&s_wait_queue, p_ntf_wait_list[i].queue_id);
        }
    }
unlock:
    osi_mutex_unlock(&s_nci_event);
    osi_mutex_unlock(&s_nci_lock);
    return ret;
}

/**
 * @brief 向指定的Data通道传输数据并等待返回
 *
 * @param channel 发送数据的通道
 * @param cmd 需要发送的数据
 * @param rsp 用于保存返回数据的指针
 * @param timeout 等待超时时间
 * @return NCI_STATUS_OK: 发送成功且获取到RSP
 *         NCI_STATUS_EXT_CMD_SEND_FAILED: 发送失败
*/
tNCI_STATUS nci_tp_send_data(tNCI_DATA_CHANNEL *channel, tNCI_BUF *cmd, tNCI_BUF *rsp, uint32_t timeout) {
    if (!s_nci_initialized) {
        return NCI_STATUS_EXT_NOT_INITIALIZED;
    }
    if (cmd == NULL || rsp == NULL || channel == NULL) {
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;

    if (osi_mutex_lock(&channel->mutex) != NFC_STATUS_OK) {
        ret = NCI_STATUS_EXT_GET_LOCK_FAILED;
        return ret;
    }

    cmd->head.gid = channel->conn_id;

    tTIMESTAMP start;
    if (osi_boot_time_ms(&start) != NFC_STATUS_OK) {
        ret = NCI_STATUS_EXT_FAILED;
        goto cleanup;
    }
    tTIMESTAMP timeout_time = start + timeout;

    ret = write_nci_buf(cmd, channel, timeout_time);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("write data cmd failed");
        goto cleanup;
    }
    tNCI_WAIT_BUF rsp_wait = {
        .buf = rsp,
        .head.gid = channel->conn_id,
        .rsp_status = NCI_STATUS_FAILED,
    };
    channel->wait_buf = &rsp_wait;

    // 等待RSP
    while (true) {
        tTIMESTAMP curr;
        if (osi_boot_time_ms(&curr) != NFC_STATUS_OK) {
            ret = NCI_STATUS_EXT_FAILED;
            goto cleanup;
        }
        if (curr >= timeout_time) {
            ret = NCI_STATUS_EXT_TIMEOUT;
            goto cleanup;
        }

        uint32_t remain_timeout = timeout_time - curr;
        tNFC_STATUS wait_ret = osi_mutex_wait(&channel->mutex, remain_timeout);
        if (wait_ret == NFC_STATUS_OK) {
            // 被其他线程唤醒，检查是否收到RSP
            if (rsp_wait.is_received) {
                // 收到RSP，退出循环
                ret = rsp_wait.rsp_status;
                break;
            } else {
                // 此次唤醒可能是收到了Credit NTF，继续等待，直到超时
                continue;
            }
        } else if (wait_ret == NFC_STATUS_TIMEOUT) {
            // 等待超时，退出循环
            ret = NCI_STATUS_EXT_TIMEOUT;
            goto cleanup;
        } else {
            // 其他错误，退出循环
            ret = NCI_STATUS_EXT_WAIT_FAILED;
            goto cleanup;
        }
    }
cleanup:
    channel->wait_buf = NULL;
    osi_mutex_unlock(&channel->mutex);
    return ret;
}

/**
 * @brief 异步发送Data数据，不等待RSP
 *
 * @param channel 发送数据的通道
 * @param data 待发送的数据
 * @param timeout 等待credit的超时时间
 *
 * @return NCI_STATUS_OK: 发送成功，其他情况返回对应错误码
 */
tNCI_STATUS nci_tp_send_data_async(tNCI_DATA_CHANNEL *channel, tNCI_BUF *data, uint32_t timeout) {
    if (!s_nci_initialized) {
        NFCLOG_E("nci is not initialized");
        return NCI_STATUS_EXT_NOT_INITIALIZED;
    }
    if (data == NULL || channel == NULL) {
        NFCLOG_E("param is invalid, data or channel is NULL");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;

    if (osi_mutex_lock(&channel->mutex) != NFC_STATUS_OK) {
        NFCLOG_E("get lock failed");
        ret = NCI_STATUS_EXT_GET_LOCK_FAILED;
        return ret;
    }

    data->head.gid = channel->conn_id;

    tTIMESTAMP start;
    if (osi_boot_time_ms(&start) != NFC_STATUS_OK) {
        ret = NCI_STATUS_EXT_FAILED;
        NFCLOG_E("get curr time failed");
        goto cleanup;
    }
    tTIMESTAMP timeout_time = start + timeout;

    ret = write_nci_buf(data, channel, timeout_time);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("write data failed, ret=%d", ret);
        goto cleanup;
    }
cleanup:
    osi_mutex_unlock(&channel->mutex);
    return ret;
}

/**
 * @brief 初始化NFC功能
 *
 * @return NCI_STATUS_OK: 初始化成功，其他情况返回对应错误码
 */
tNCI_STATUS nci_tp_core_initialized() {
    return request_nfc_event(NFC_EVT_POST_INIT_CPLT);
}

static void tp_event_callback(tNFC_EVENT event, tNFC_STATUS status) {
    if (!mq_send_msg_with_args(&s_mq_nci, NCI_EVENT_HAL_EVENT_RECV, (uint32_t)event, (uint64_t)status, NULL)) {
        NFCLOG_E("send hal event=%d failed", event);
    }
}

/**
 * @brief 传输层内部分发，运行在传输层线程
 */
static bool internal_dispatch(tNCI_BUF *buf) {
    bool is_handled = false;
    tNCI_HEAD *head = &buf->head;
    uint8_t mt = head->mt;
    uint8_t gid = head->gid;
    uint8_t oid = head->oid;

    if (mt == NCI_NTF) {
        if (gid == NCI_CORE) {
            if (oid == NCI_CORE_CONN_CREDITS) {
                // 6006
                nci_core_conn_credits(buf->data, buf->len);
                is_handled = true;
            } else if (oid == NCI_CORE_INTERFACE_ERROR) {
                // 6008
                if (buf->data && buf->len == 2) {
                    uint8_t status = buf->data[0];
                    uint8_t conn_id = buf->data[1];
                    tNCI_STATUS ret = notify_data_recv(conn_id, status, NULL);
                    if (ret == NCI_STATUS_OK) {
                        // 只有在通知成功的情况下才认为已经处理
                        is_handled = true;
                    }
                }
            }
        }
    }
    return is_handled;
}

/**
 * @brief 处理接收到的NCI控制数据
*/
static tNCI_STATUS handle_control_packet_recv(tNCI_BUF *buf) {
    if (!buf) {
        NFCLOG_E("invalid data");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    tNCI_HEAD *head = &buf->head;
    buf->head.pbf = 0;
    NFCLOG_I("recv: %02X%02X", head->hdr[0], head->hdr[1]);
    if (internal_dispatch(buf)) {
        // 内部分发成功，直接返回，不再继续处理
        return NCI_STATUS_OK;
    }
    if (osi_mutex_lock(&s_nci_event) != NFC_STATUS_OK) {
        NFCLOG_E("lock nci mutex failed");
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }
    if (!s_nci_initialized) {
        NFCLOG_E("nci not initialized");
        osi_mutex_unlock(&s_nci_event);
        return NCI_STATUS_EXT_NOT_INITIALIZED;
    }
    // 遍历等待队列中是否有接收者，如果有，则通知等待者并将其移出等待队列
    tQUEUE_NODE *curr = s_wait_queue.root;
    // 先找到匹配的WAIT_BUF
    while (curr) {
        tNCI_WAIT_BUF *wait_buf = curr->data;
        if (wait_buf && memcmp(wait_buf->head.hdr, head, sizeof(tNCI_HEAD)) == 0) {
            break;
        }
        curr = curr->next;
    }
    if (curr) {
        tNCI_WAIT_BUF *wait_buf = curr->data;
        if (head->mt == NCI_RSP && buf->len > 0) {
            // 记录RSP状态
            wait_buf->rsp_status = buf->data[0];
        }
        if (wait_buf->buf) {
            SWAP_NCI_BUF(wait_buf->buf, buf);
        }
        wait_buf->is_received = true;
        pq_remove(&s_wait_queue, curr->id);
        osi_mutex_notify(&s_nci_event);
        NFCLOG_D("notify recv: %02X%02X", head->hdr[0], head->hdr[1]);
        osi_mutex_unlock(&s_nci_event);
        return NCI_STATUS_OK;
    }
    osi_mutex_unlock(&s_nci_event);

    // 如果没有接收者，则交给分发系统处理
    tNCI_STATUS ret = nci_task_post(NCI_TASK_EVT_TRANSPORT_DISPATCH, 0, 0, buf);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("post dispatch failed, ret=%d", ret);
    } else {
        // 发送成功, buf交由任务系统负责回收
        ret = NCI_STATUS_EXT_NOT_FREE;
    }
    return ret;
}

/**
 * @brief 通知DATA数据已收到
 * @param conn_id 需要通知的通道
 * @param status 接收状态
 * @param buf 接收到的数据，可以为空
 */
static tNCI_STATUS notify_data_recv(uint8_t conn_id, uint8_t status, tNCI_BUF *buf) {
    if (!s_nci_initialized) {
        NFCLOG_E("nci not initialized");
        return NCI_STATUS_EXT_STATE_INCORRECT;
    }
    tNCI_DATA_CHANNEL *channel = nci_data_find_channel(conn_id);
    if (channel == NULL) {
        NFCLOG_E("invalid conn id: %d", conn_id);
        return NCI_STATUS_EXT_INVALID_PARAM;
    }

    if (osi_mutex_lock(&channel->mutex) != NFC_STATUS_OK) {
        NFCLOG_E("lock data channel(%d) mutex failed", conn_id);
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }

    tNCI_WAIT_BUF *wait_buf = channel->wait_buf;
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;

    if (wait_buf) {
        if (wait_buf->buf && buf) {
            SWAP_NCI_BUF(wait_buf->buf, buf);
        }
        wait_buf->is_received = true;
        wait_buf->rsp_status = status;

        channel->wait_buf = NULL;
        if (osi_mutex_notify(&channel->mutex) != NFC_STATUS_OK) {
            NFCLOG_E("notify data channel(%d) status=%d failed", conn_id, status);
            ret = NCI_STATUS_EXT_FAILED;
        } else {
            NFCLOG_D("notify data channel(%d) status=%d success", conn_id, status);
            ret = NCI_STATUS_OK;
        }
    } else if (buf) {
        // 如果没有等待者，则交给分发系统处理
        ret = nci_task_post(NCI_TASK_EVT_TRANSPORT_DISPATCH, 0, 0, buf);
        if (ret != NCI_STATUS_OK) {
            NFCLOG_E("post dispatch failed, ret=%d", ret);
        } else {
            // 发送成功, buf交由任务系统负责回收
            ret = NCI_STATUS_EXT_NOT_FREE;
        }
    }
    osi_mutex_unlock(&channel->mutex);
    return ret;
}

/**
 * @brief 处理接收到NCI DATA数据
*/
static tNCI_STATUS handle_data_recv(tNCI_BUF *buf) {
    if (!s_nci_initialized) {
        NFCLOG_E("nci not initialized");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    if (!buf) {
        NFCLOG_E("invalid data");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    return notify_data_recv(buf->head.gid, NCI_STATUS_OK, buf);
}

static void handle_hal_event(tNFC_EVENT event, tNFC_STATUS status) {
    NFCLOG_I("recv hal event=%d, status=%d", event, status);
    tNFC_WAIT_EVENT *p_wait_event = (tNFC_WAIT_EVENT*) s_p_wait_event;
    if (p_wait_event && p_wait_event->event == event) {
        if (osi_mutex_lock(&s_nci_event) != NFC_STATUS_OK) {
            NFCLOG_E("lock nci mutex failed");
            return;
        }
        p_wait_event->status = status;
        p_wait_event->is_received = true;
        NFCLOG_D("notify event=%d arrived, with status=%d", event, status);
        osi_mutex_notify(&s_nci_event);
        osi_mutex_unlock(&s_nci_event);
        return;
    }
    // TODO 处理没有调用者等待的事件
}

/**
 * @brief NCI消息队列处理函数
*/
static bool handle_data_recv_task(uint32_t what, uint32_t arg1, uint64_t arg2, void* args) {
    (void) arg1;
    (void) arg2;
    NFCLOG_D("handle msg: %d", what);
    bool free_args = true;
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    switch (what) {
    case NCI_EVENT_CONTROL_PACKET_RECV:
        ret = handle_control_packet_recv((tNCI_BUF*)args);
        break;
    case NCI_EVENT_DATA_RECV:
        ret = handle_data_recv((tNCI_BUF*)args);
        break;
    case NCI_EVENT_HAL_EVENT_RECV:
        handle_hal_event((tNFC_EVENT)arg1, (tNFC_STATUS)arg2);
        ret = NCI_STATUS_OK;
        break;
    case NCI_TASK_EVT_TRANSPORT_DISPATCH:
        nci_process_dispatch((tNCI_BUF*)args);
        ret = NCI_STATUS_OK;
        break;
    case NCI_TASK_EVT_TRANSPORT_INJECT_NTF:
        NFCLOG_I("inject ntf");
        tp_data_callback((uint16_t) arg1, (uint8_t*) args);
        ret = NCI_STATUS_OK;
    default:
        NFCLOG_E("unknown msg: %d", what);
        break;
    }
    if (ret == NCI_STATUS_EXT_NOT_FREE) {
        free_args = false;
    }
    return free_args;
}

/**
 * @brief NCI消息队列清理函数
*/
static void mq_cleanup(uint32_t what, uint32_t arg1, uint64_t arg2, void *args) {
    (void) arg1;
    (void) arg2;
    switch (what)
    {
    case NCI_EVENT_DATA_RECV:
    case NCI_EVENT_CONTROL_PACKET_RECV:
    case NCI_TASK_EVT_TRANSPORT_DISPATCH:
        if (args) {
            free_nci_buf((tNCI_BUF*) args);
        }
        break;
    case NCI_TASK_EVT_TRANSPORT_INJECT_NTF:
        if (args) {
            osi_free(args);
        }
        break;
    default:
        break;
    }
}

/**
 * @brief NCI数据通道回调函数
*/
static void tp_data_callback(uint16_t data_len, uint8_t* data) {
    if (data == NULL || data_len < NCI_BUF_HEAD_SIZE) {
        NFCLOG_E("invalid data, data=%p, data_len=%d", data, data_len);
        return;
    }

    tQUEUE_NODE *curr = s_pbf_queue.root;
    tNCI_BUF *buf = NULL;
    tNCI_HEAD *head = (tNCI_HEAD*) data;
    while(curr) {
        tNCI_BUF *curr_buf = (tNCI_BUF*) curr->data;
        if (curr_buf) {
            tNCI_HEAD *curr_head = &curr_buf->head;
            if (curr_head->mt == head->mt && curr_head->gid == head->gid && curr_head->oid == head->oid) {
                // 找到匹配的PBF消息
                NFCLOG_I("found pbf message");
                buf = (tNCI_BUF*) pq_remove(&s_pbf_queue, curr->id);;
                break;
            }
        }
        curr = curr->next;
    }
    if (!buf) {
        // 没有匹配的PBF消息，申请新的buf
        buf = alloc_nci_buf_with_cap((data[0] << 8) | data[1], data_len - NCI_BUF_HEAD_SIZE);
        if (!buf) {
            NFCLOG_E("alloc nci buf failed");
            return;
        }
    }
    ARRAY_TO_BUF(buf, data + NCI_BUF_HEAD_SIZE, data_len - NCI_BUF_HEAD_SIZE);

    if (head->pbf) {
        // PBF 消息，需要等待后续消息
        NFCLOG_I("PBF message received, waiting for remaining data");
        if (!pq_enqueue(&s_pbf_queue, buf, 0, 0, NULL)) {
            NFCLOG_E("enqueue pbf failed");
            free_nci_buf(buf);
        }
        return;
    }

    tMQ_MSG *msg = mq_alloc_msg(&s_mq_nci);
    if (msg == NULL) {
        return;
    }
    msg->args = buf;
    if (buf->head.mt == NCI_DATA) {
        // DATA_PACKET
        msg->what = NCI_EVENT_DATA_RECV;
    } else {
        // CONTROL_PACKET
        msg->what = NCI_EVENT_CONTROL_PACKET_RECV;
    }
    bool result = mq_send_msg(&s_mq_nci, msg);
    if (!result) {
        NFCLOG_E("mq_send_msg Failed");
        goto cleanup;
    }
    return;
cleanup:
    mq_free_msg(msg);
}

/**
 * @brief pbf等待队列清理函数
*/
static void cleanup_pbf_queue(tQUEUE_ID id, tQUEUE_TAG tag, void* data) {
    (void) id;
    (void) tag;
    if (data) {
        free_nci_buf((tNCI_BUF *)data);
    }
}

/**
 * @brief NCI层初始化
 *
 * @note nci_core/nfcee/rf等接口函数需要nci_init成功后才能使用
 *
 * @return 初始化成功返回NCI_STATUS_OK，否则返回错误码
*/
tNCI_STATUS nci_init() {
    if (osi_mutex_init(&s_nci_lock) != NFC_STATUS_OK) {
        NFCLOG_E("init nci lock failed");
        return NCI_STATUS_FAILED;
    }
    tNFC_STATUS ret = osi_mutex_init(&s_nci_event);
    if (ret != NFC_STATUS_OK) {
        NFCLOG_E("init nci mutex failed");
        goto cleanup_lock;
    }
    if (!pq_init(&s_wait_queue, pq_comp_min, NULL)) {
        NFCLOG_E("init wait queue failed");
        goto cleanup_mutex;
    }
    if (!pq_init(&s_pbf_queue, pq_comp_min, cleanup_pbf_queue)) {
        NFCLOG_E("init pbf queue failed");
        goto cleanup_wait_queue;
    }
    if (!mq_init(&s_mq_nci, handle_data_recv_task, mq_cleanup)) {
        NFCLOG_E("init nci queue failed");
        goto cleanup_pbf_queue;
    }
    if (!mq_start(&s_mq_nci)) {
        NFCLOG_E("start nci queue failed");
        goto cleanup_mq;
    }
    if (nci_task_init() != NCI_STATUS_OK) {
        NFCLOG_E("init nci task failed");
        goto cleanup_mq;
    }
    if (nci_task_register(handle_data_recv_task, mq_cleanup, NCI_TASK_EVT_TRANSPORT_GROUP) != NCI_STATUS_OK) {
        NFCLOG_E("register nci task failed");
        goto cleanup_nci_task;
    }
    if (request_nfc_event(NFC_EVT_OPEN_CPLT) != NCI_STATUS_OK) {
        NFCLOG_E("open transport failed");
        goto cleanup_nci_task;
    }
    s_nci_initialized = true;
    return NCI_STATUS_OK;
cleanup_nci_task:
    nci_task_deinit();
cleanup_mq:
    mq_deinit(&s_mq_nci);
cleanup_pbf_queue:
    pq_deinit(&s_pbf_queue, false);
cleanup_wait_queue:
    pq_deinit(&s_wait_queue, false);
cleanup_mutex:
    osi_mutex_deinit(&s_nci_event);
cleanup_lock:
    osi_mutex_deinit(&s_nci_lock);
    return NCI_STATUS_FAILED;
}

/**
 * @brief 设置NCI开关状态为false,防止其他线程继续发送NCI指令
 */
static tNCI_STATUS disable_nci_status() {
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    if (osi_mutex_lock(&s_nci_lock) != NFC_STATUS_OK) {
        NFCLOG_E("lock nci lock failed");
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }
    if (osi_mutex_lock(&s_nci_event) != NFC_STATUS_OK) {
        NFCLOG_E("lock nci mutex failed");
        ret = NCI_STATUS_EXT_GET_LOCK_FAILED;
        goto unlock_nci_lock;
    }
    if (!s_nci_initialized) {
        NFCLOG_E("nci not initialized");
        ret = NCI_STATUS_EXT_NOT_INITIALIZED;
        goto unlock_nci_event;
    }
    s_nci_initialized = false;
    ret = NCI_STATUS_OK;
unlock_nci_event:
    osi_mutex_unlock(&s_nci_event);
unlock_nci_lock:
    osi_mutex_unlock(&s_nci_lock);
    return ret;
}

/**
 * @brief NCI层退出
 *
 * @note nci_deinit后，nci_core/nfcee/rf等接口函数不能再使用
 *
 * @param is_shutdown 是否进入关机模式，true为关机模式，false为正常关闭NFC
 *
 * @return 退出成功返回NCI_STATUS_OK，否则返回错误码
*/
tNCI_STATUS nci_deinit(bool is_shutdown) {
    tNCI_STATUS ret = disable_nci_status();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("close nci failed, ret=%d", ret);
        return ret;
    }
    if (is_shutdown) {
        if (tp_close(NFC_CLOSE_TYPE_HOST_SWITCHED_OFF) != NFC_STATUS_OK) {
            NFCLOG_E("shutdown transport failed");
        }
    } else {
        if (request_nfc_event(NFC_EVT_CLOSE_CPLT) != NCI_STATUS_OK) {
            NFCLOG_E("close transport failed");
        }
    }
    if (nci_task_unregister(NCI_TASK_EVT_TRANSPORT_GROUP) != NCI_STATUS_OK) {
        NFCLOG_E("unregister nci task failed");
    }
    if (nci_task_deinit() != NCI_STATUS_OK) {
        NFCLOG_E("deinit nci task failed");
    }
    if (!pq_deinit(&s_wait_queue, false)) {
        NFCLOG_E("deinit wait queue failed");
    }
    if (!pq_deinit(&s_pbf_queue, true)) {
        NFCLOG_E("deinit pbf queue failed");
    }
    if (!mq_deinit(&s_mq_nci)) {
        NFCLOG_E("deinit nci queue failed");
    }
    if (osi_mutex_deinit(&s_nci_event) != NFC_STATUS_OK) {
        NFCLOG_E("deinit nci mutex failed");
    }
    if (osi_mutex_deinit(&s_nci_lock) != NFC_STATUS_OK) {
        NFCLOG_E("deinit nci lock failed");
    }
    return NCI_STATUS_OK;
}

/**
 * @brief 向传输层写入NCI BUF，会自动将NCI BUF拆分成多个NCI MESSAGE依次下发
 *
 * @param buf 需要写入的NCI消息
 * @param channel 当前NCI消息所属的通道，只有DATA数据才需要该参数，NCI控制指令传NULL
 * @param timeout_time 等待DATA Credit的截止时间点，如果当前是控制指令则该参数传0
 *
 * @return 写入成功返回NCI_STATUS_OK，否则返回错误码
*/
static tNCI_STATUS write_nci_buf(tNCI_BUF *buf, tNCI_DATA_CHANNEL *channel, tTIMESTAMP timeout_time) {
    if (!buf) {
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    tNCI_MESSAGE *msg = osi_calloc(sizeof(tNCI_MESSAGE));
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    if (!msg) {
        NFCLOG_E("alloc NCI_MESSAGE failed");
        return NCI_STATUS_EXT_ALLOC_FAILED;
    }
    if (!osi_memcpy_s(&msg->head, sizeof(tNCI_HEAD), &buf->head, sizeof(tNCI_HEAD))) {
        NFCLOG_E("copy NCI_HEAD failed");
        goto cleanup;
    }
    if (buf->len == 0) {
        // 当Payload为空时，直接发送NCI_MESSAGE
        ret = write_nci_message(msg, channel, timeout_time);
        if (ret != NCI_STATUS_OK) {
            NFCLOG_E("write nci failed, ret=%d", ret);
        }
        goto cleanup;
    }
    uint16_t max_payload_size = NCI_BUF_PAYLOAD_DEFAULT_SIZE;
    if (channel && channel->max_data_packet_payload_size < max_payload_size) {
        // 如果当前是数据通道，则使用该通道的最大数据包payload大小
        max_payload_size = channel->max_data_packet_payload_size;
    }
    uint16_t pos = 0;
    while (pos < buf->len) {
        uint16_t write_len = buf->len - pos;
        if (write_len > max_payload_size) {
            write_len = max_payload_size;
            msg->head.pbf = 1;
        } else {
            msg->head.pbf = 0;
        }
        msg->len = (uint8_t) write_len;
        if (!osi_memcpy_s(msg->payload, NCI_BUF_PAYLOAD_DEFAULT_SIZE, buf->data + pos, write_len)) {
            NFCLOG_E("copy NCI_MESSAGE payload failed");
            goto cleanup;
        }
        ret = write_nci_message(msg, channel, timeout_time);
        if (ret != NCI_STATUS_OK) {
            NFCLOG_E("write nci failed, ret=%d", ret);
            goto cleanup;
        }
        pos += write_len;
    }

cleanup:
    osi_free(msg);
    return ret;
}

/**
 * @brief 向传输层写入NCI MESSAGE
 *
 * @param msg 需要写入的NCI消息
 * @param channel 当前NCI消息所属的通道，只有DATA数据才需要该参数，NCI控制指令传NULL
 * @param timeout_time 等待DATA Credit的截止时间点，如果当前是控制指令则该参数传0
 *
 * @return 写入成功返回NCI_STATUS_OK，否则返回错误码
*/
static tNCI_STATUS write_nci_message(tNCI_MESSAGE *msg, tNCI_DATA_CHANNEL *channel, tTIMESTAMP timeout_time) {
    // 等待DATA Credit
    while (channel && channel->credit == 0) {
        tTIMESTAMP curr;
        if (osi_boot_time_ms(&curr) != NFC_STATUS_OK) {
            return NCI_STATUS_EXT_FAILED;
        }
        if (curr >= timeout_time) {
            return NCI_STATUS_EXT_TIMEOUT;
        }

        uint32_t remain_timeout = timeout_time - curr;
        NFCLOG_I("wait credit: remain=%d ms", remain_timeout);
        tNFC_STATUS wait_ret = osi_mutex_wait(&channel->mutex, remain_timeout);

        if (wait_ret == NFC_STATUS_TIMEOUT) {
            return NCI_STATUS_EXT_TIMEOUT;
        } else if (wait_ret != NFC_STATUS_OK) {
            return NCI_STATUS_EXT_WAIT_FAILED;
        }
    }

    tNFC_STATUS ret = tp_write(msg->hdr, ((uint16_t)msg->len) + NCI_BUF_HEAD_SIZE);
    if (ret != NFC_STATUS_OK) {
        NFCLOG_E("write nci failed, ret=%d", ret);
        return NCI_STATUS_EXT_TP_ERROR;
    }
    if (channel) {
        channel->credit--;
    }
    return NCI_STATUS_OK;
}

/**
 * @brief 根据event调用对应的tp函数并等待event到达或超时
 */
static tNCI_STATUS request_nfc_event(tNFC_EVENT event) {
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    // 先获取NCI锁，防止其他线程发送NCI指令或调用tp函数
    if (osi_mutex_lock(&s_nci_lock) != NFC_STATUS_OK) {
        NFCLOG_E("lock nci lock failed");
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }
    // 再获取NCI事件锁用于后续等待事件
    if (osi_mutex_lock(&s_nci_event) != NFC_STATUS_OK) {
        NFCLOG_E("lock nci event failed");
        ret = NCI_STATUS_EXT_GET_LOCK_FAILED;
        goto unlock;
    }

    // 设置等待事件
    tNFC_WAIT_EVENT wait_event = {
        .event = event,
        .status = NFC_STATUS_FAILED,
        .is_received = false,
    };
    s_p_wait_event = &wait_event;

    tNFC_STATUS tp_ret = NFC_STATUS_FAILED;
    uint64_t wait_time = 0;
    // 根据等待的EVENT，调用对应tp函数
    switch (event) {
        case NFC_EVT_OPEN_CPLT:
            tp_ret = tp_open(tp_event_callback, tp_data_callback);
            wait_time = s_nfc_open_timeout;
            break;
        case NFC_EVT_CLOSE_CPLT:
            tp_ret = tp_close(NFC_CLOSE_TYPE_DISABLE);
            wait_time = s_nfc_close_timeout;
            break;
        case NFC_EVT_POST_INIT_CPLT:
            if (!s_nci_initialized) {
                NFCLOG_E("nci not initialized");
                ret = NCI_STATUS_EXT_NOT_INITIALIZED;
                goto unlock;
            }
            tp_ret = tp_core_init();
            wait_time = s_core_init_timeout;
            break;
        default:
            tp_ret = NFC_STATUS_FAILED;
            NFCLOG_E("not support event=%d", event);
            break;
    }
    if (tp_ret != NFC_STATUS_OK) {
        NFCLOG_E("call hal failed, event=%d, ret=%d", event, tp_ret);
        ret = NCI_STATUS_EXT_FAILED;
        goto unlock;
    }

    if (!wait_event.is_received) {
        // 开始等待
        NFCLOG_I("start wait event=%d, timeout=%" PRIu64, event, wait_time);
        tNFC_STATUS wait_ret = osi_mutex_wait(&s_nci_event, wait_time);
        if (wait_ret == NFC_STATUS_TIMEOUT) {
            NFCLOG_E("wait event=%d timeout", event);
            ret = NCI_STATUS_EXT_FAILED;
            goto unlock;
        } else if (wait_ret != NFC_STATUS_OK) {
            NFCLOG_E("wait event=%d failed, ret=%d", event, wait_ret);
            ret = NCI_STATUS_EXT_FAILED;
            goto unlock;
        }
    } else {
        // 已经收到事件，无需等待
    }

    if (wait_event.status != NFC_STATUS_OK) {
        // 等到了事件，但是状态不是OK
        NFCLOG_E("request event=%d failed, status=%d", event, wait_event.status);
        ret = NCI_STATUS_EXT_FAILED;
        goto unlock;
    }
    ret = NCI_STATUS_OK;
unlock:
    s_p_wait_event = NULL;
    osi_mutex_unlock(&s_nci_event);
    osi_mutex_unlock(&s_nci_lock);
    return ret;
}

